package informationretrieval;
import static informationretrieval.Constants.NAME_ID;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.apache.lucene.document.Document;

public class Functions {
	
	// Class variables
	private final static String TAG = Functions.class.getSimpleName();

	/**
	 * Private constructor to escape instantiation
	 */
	private Functions() {
	}

	/**
	 * Gets the stop words from the stop words file
	 * 
	 * @param stopWordsFileName
	 *            The stop words file name
	 * @return A vector with the stop words
	 * @throws NumberFormatException
	 * @throws IOException
	 */
	public static Vector<String> getStopWords(String stopWordsFileName)
			throws NumberFormatException, IOException {
		String line;
		File stopWordsFile = new File(stopWordsFileName);
		FileInputStream fileInputStream = new FileInputStream(stopWordsFile);
		BufferedReader bufferedReader = new BufferedReader(
				new InputStreamReader(fileInputStream));
		Vector<String> stopWordList = new Vector<String>();

		while ((line = bufferedReader.readLine()) != null) {
			stopWordList.add(line.trim());
		}

		bufferedReader.close();

		return stopWordList;
	}

	/**
	 * Update the results according to the number of requested results (5 or 10)
	 * 
	 * @param result
	 *            The search result set
	 * @param queryId
	 *            The id of the query that has been looked up
	 * @param resultsCounter
	 *            A class with the relevant results for the query
	 * @param maxResults
	 *            The max result for the query (5 || 10)
	 * @throws IOException
	 */
	public static void updateResultsCount(SearchResult result, int queryId, /* output */
			ResultSet resultsCounter, int maxResults) throws IOException {
		int maxResultsToUpdate = Math.min(maxResults,
				result.getScoreDoc().length);

		if (maxResults == 0) {
			maxResultsToUpdate = result.getScoreDoc().length;
		}

		for (int rank = 0; rank < maxResultsToUpdate; rank++) {
			int docId = result.getScoreDoc()[rank].doc;
			float score = result.getScoreDoc()[rank].score; // TODO: remove???
			Document doc = result.getDoc(docId);
			int doc_id = Integer.parseInt(doc.getField(NAME_ID).stringValue());

			resultsCounter.AddResults(queryId, doc_id);
		}
	}

	/**
	 * Calculate and save the comparing results for a given result set
	 * 
	 * @param truthResult
	 *            The truth result
	 * @param actual
	 *            The result we got
	 */
	public static void calculateAndSaveComparingResults(
			ResultSet truthResult, ResultSet actual) {

		int truePositive = 0;
		int falsePositive = 0;
		// please pay special attention for handling the false negative!!!
		// this is only example how you can calculate it but you should
		// make sure that you calculate it according to the rank!!!!(unlike this
		// code!)
		int falseNegative = 0;

		for (int queryId : truthResult.mResults.keySet()) {
			// the reason for cloning the vectors is that the set operation
			// change the vectors
			Vector<Integer> intersectResultsVector = new Vector<Integer>(
					truthResult.mResults.get(queryId));
			intersectResultsVector.retainAll(actual.mResults.get(queryId));
			truePositive = truePositive + intersectResultsVector.size();
			if (actual.mResults.containsKey(queryId)) {
				Vector<Integer> subtract_results_vector = new Vector<Integer>(
						actual.mResults.get(queryId));
				subtract_results_vector.removeAll(truthResult.mResults
						.get(queryId));
				falsePositive = falsePositive + subtract_results_vector.size();

				// should be fix! to compare by rank
				Vector<Integer> falseNegativeResultSet = new Vector<Integer>(
						truthResult.mResults.get(queryId));
				falseNegativeResultSet.removeAll(actual.mResults.get(queryId));
				falseNegative = falseNegative + falseNegativeResultSet.size();
			}
		}

		float Percision = (float) truePositive
				/ (float) (truePositive + falsePositive);
		Log.trace("Percision: " + Percision);
	}

	/**
	 * A method to get the false result set document id as list
	 * @param corpusSize The corpus size
	 * @param trueResultSet The true result set for a query
	 * @return The false result set
	 */
	public static List<Integer> getFalseResultSet(int corpusSize,
			List<Integer> trueResultSet) {
		List<Integer> falseResultSet = new ArrayList<Integer>();
		for(int i = 0; i < corpusSize; i++) {
			Integer id = new Integer(i);
			if(!trueResultSet.contains(id)) {
				falseResultSet.add(id);
			}
		}
		
		return falseResultSet;
	}
}